package service

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"

	"goldtree/internal/dao"
	"goldtree/internal/entity"
)

// StrategyService 策略服务
type StrategyService struct{}

var Strategy = StrategyService{}

// CreateStrategyReq 创建策略请求
type CreateStrategyReq struct {
	Name        string                 `json:"name" v:"required|length:1,100#策略名称不能为空|策略名称长度不能超过100位"`
	Type        string                 `json:"type" v:"required|length:1,50#策略类型不能为空|策略类型长度不能超过50位"`
	Description string                 `json:"description"`
	Parameters  map[string]interface{} `json:"parameters"`
	StockPool   []string               `json:"stock_pool"`
}

// UpdateStrategyReq 更新策略请求
type UpdateStrategyReq struct {
	Id          int                    `json:"id" v:"required|min:1#ID不能为空|ID必须大于0"`
	Name        string                 `json:"name" v:"required|length:1,100#策略名称不能为空|策略名称长度不能超过100位"`
	Description string                 `json:"description"`
	Parameters  map[string]interface{} `json:"parameters"`
	StockPool   []string               `json:"stock_pool"`
	IsActive    *bool                  `json:"is_active"`
}

// GetStrategyListReq 获取策略列表请求
type GetStrategyListReq struct {
	Page     int    `json:"page" v:"min:1#页码必须大于0"`
	Limit    int    `json:"limit" v:"min:1|max:100#每页数量必须大于0|每页数量不能超过100"`
	Keyword  string `json:"keyword"`
	Type     string `json:"type"`
	Status   string `json:"status"`
	IsActive *bool  `json:"is_active"`
}

// StrategyListRes 策略列表响应
type StrategyListRes struct {
	List  []*entity.Strategy `json:"list"`
	Total int                `json:"total"`
	Page  int                `json:"page"`
	Limit int                `json:"limit"`
}

// StrategyDetailRes 策略详情响应
type StrategyDetailRes struct {
	Strategy    *entity.Strategy                  `json:"strategy"`
	Performance *entity.StrategyPerformanceEntity `json:"performance"`
	Positions   []*entity.StrategyPosition        `json:"positions"`
	Signals     []*entity.TradingSignal           `json:"recent_signals"`
}

// Create 创建策略
func (s *StrategyService) Create(ctx context.Context, req *CreateStrategyReq) (*entity.Strategy, error) {
	// 验证策略名称是否已存在
	exists, err := dao.Strategy.IsNameExists(ctx, req.Name)
	if err != nil {
		return nil, gerror.Wrap(err, "检查策略名称失败")
	}
	if exists {
		return nil, gerror.New("策略名称已存在")
	}

	// 序列化参数和股票池
	parametersJson, err := json.Marshal(req.Parameters)
	if err != nil {
		return nil, gerror.Wrap(err, "序列化策略参数失败")
	}

	stockPoolJson, err := json.Marshal(req.StockPool)
	if err != nil {
		return nil, gerror.Wrap(err, "序列化股票池失败")
	}

	// 构建策略实体
	strategyEntity := &entity.Strategy{
		Name:        req.Name,
		Type:        req.Type,
		Description: req.Description,
		Parameters:  string(parametersJson),
		StockPool:   string(stockPoolJson),
		IsActive:    true,
		Status:      "idle",
		RunCount:    0,
		ErrorCount:  0,
	}

	// 插入数据库
	id, err := dao.Strategy.Insert(ctx, strategyEntity)
	if err != nil {
		return nil, gerror.Wrap(err, "创建策略失败")
	}

	// 返回创建的策略信息
	strategyEntity.Id = int(id)
	g.Log().Info(ctx, "创建策略成功", "id", id, "name", req.Name, "type", req.Type)
	return strategyEntity, nil
}

// Update 更新策略
func (s *StrategyService) Update(ctx context.Context, req *UpdateStrategyReq) error {
	// 检查策略是否存在
	existingStrategy, err := dao.Strategy.GetById(ctx, req.Id)
	if err != nil {
		return gerror.Wrap(err, "获取策略信息失败")
	}
	if existingStrategy == nil {
		return gerror.New("策略不存在")
	}

	// 检查名称是否与其他策略冲突
	if existingStrategy.Name != req.Name {
		exists, err := dao.Strategy.IsNameExists(ctx, req.Name)
		if err != nil {
			return gerror.Wrap(err, "检查策略名称失败")
		}
		if exists {
			return gerror.New("策略名称已存在")
		}
	}

	// 序列化参数和股票池
	parametersJson, err := json.Marshal(req.Parameters)
	if err != nil {
		return gerror.Wrap(err, "序列化策略参数失败")
	}

	stockPoolJson, err := json.Marshal(req.StockPool)
	if err != nil {
		return gerror.Wrap(err, "序列化股票池失败")
	}

	// 构建更新数据
	updateData := &entity.Strategy{
		Name:        req.Name,
		Description: req.Description,
		Parameters:  string(parametersJson),
		StockPool:   string(stockPoolJson),
	}

	if req.IsActive != nil {
		updateData.IsActive = *req.IsActive
	}

	// 更新数据库
	err = dao.Strategy.Update(ctx, req.Id, updateData)
	if err != nil {
		return gerror.Wrap(err, "更新策略失败")
	}

	g.Log().Info(ctx, "更新策略成功", "id", req.Id, "name", req.Name)
	return nil
}

// Delete 删除策略
func (s *StrategyService) Delete(ctx context.Context, id int) error {
	// 检查策略是否存在
	strategyEntity, err := dao.Strategy.GetById(ctx, id)
	if err != nil {
		return gerror.Wrap(err, "获取策略信息失败")
	}
	if strategyEntity == nil {
		return gerror.New("策略不存在")
	}

	// 检查策略是否正在运行
	if strategyEntity.Status == "running" {
		return gerror.New("不能删除正在运行的策略，请先停止策略")
	}

	// 删除策略
	err = dao.Strategy.Delete(ctx, id)
	if err != nil {
		return gerror.Wrap(err, "删除策略失败")
	}

	g.Log().Info(ctx, "删除策略成功", "id", id, "name", strategyEntity.Name)
	return nil
}

// GetById 根据ID获取策略
func (s *StrategyService) GetById(ctx context.Context, id int) (*entity.Strategy, error) {
	strategyEntity, err := dao.Strategy.GetById(ctx, id)
	if err != nil {
		return nil, gerror.Wrap(err, "获取策略信息失败")
	}
	return strategyEntity, nil
}

// GetDetail 获取策略详情
func (s *StrategyService) GetDetail(ctx context.Context, id int) (*StrategyDetailRes, error) {
	// 获取策略基本信息
	strategyEntity, err := dao.Strategy.GetById(ctx, id)
	if err != nil {
		return nil, gerror.Wrap(err, "获取策略信息失败")
	}
	if strategyEntity == nil {
		return nil, gerror.New("策略不存在")
	}

	// 获取策略性能
	performance, err := dao.StrategyPerformance.GetByStrategyId(ctx, id)
	if err != nil {
		g.Log().Warning(ctx, "获取策略性能失败", "id", id, "error", err)
	}

	// 获取策略持仓
	positions, err := dao.StrategyPosition.GetListByStrategyId(ctx, id)
	if err != nil {
		g.Log().Warning(ctx, "获取策略持仓失败", "id", id, "error", err)
		positions = []*entity.StrategyPosition{}
	}

	// 获取最近的交易信号
	signals, err := dao.TradingSignal.GetListByStrategyId(ctx, id, 1, 10)
	if err != nil {
		g.Log().Warning(ctx, "获取交易信号失败", "id", id, "error", err)
		signals = []*entity.TradingSignal{}
	}

	return &StrategyDetailRes{
		Strategy:    strategyEntity,
		Performance: performance,
		Positions:   positions,
		Signals:     signals,
	}, nil
}

// GetList 获取策略列表
func (s *StrategyService) GetList(ctx context.Context, req *GetStrategyListReq) (*StrategyListRes, error) {
	// 设置默认值
	if req.Page == 0 {
		req.Page = 1
	}
	if req.Limit == 0 {
		req.Limit = 20
	}

	// 构建查询条件
	var conditions []interface{}
	if req.Keyword != "" {
		conditions = append(conditions, "(name LIKE ? OR description LIKE ?)", "%"+req.Keyword+"%", "%"+req.Keyword+"%")
	}
	if req.Type != "" {
		condition := "type = ?"
		if len(conditions) > 0 {
			conditions[0] = fmt.Sprintf("%s AND %s", conditions[0], condition)
			conditions = append(conditions, req.Type)
		} else {
			conditions = append(conditions, condition, req.Type)
		}
	}
	if req.Status != "" {
		condition := "status = ?"
		if len(conditions) > 0 {
			conditions[0] = fmt.Sprintf("%s AND %s", conditions[0], condition)
			conditions = append(conditions, req.Status)
		} else {
			conditions = append(conditions, condition, req.Status)
		}
	}
	if req.IsActive != nil {
		condition := "is_active = ?"
		if len(conditions) > 0 {
			conditions[0] = fmt.Sprintf("%s AND %s", conditions[0], condition)
			conditions = append(conditions, *req.IsActive)
		} else {
			conditions = append(conditions, condition, *req.IsActive)
		}
	}

	// 获取列表
	strategies, err := dao.Strategy.GetList(ctx, req.Page, req.Limit, conditions...)
	if err != nil {
		return nil, gerror.Wrap(err, "获取策略列表失败")
	}

	// 获取总数
	total, err := dao.Strategy.GetCount(ctx, conditions...)
	if err != nil {
		return nil, gerror.Wrap(err, "获取策略总数失败")
	}

	return &StrategyListRes{
		List:  strategies,
		Total: total,
		Page:  req.Page,
		Limit: req.Limit,
	}, nil
}

// Start 启动策略
func (s *StrategyService) Start(ctx context.Context, id int) error {
	// 检查策略是否存在
	strategyEntity, err := dao.Strategy.GetById(ctx, id)
	if err != nil {
		return gerror.Wrap(err, "获取策略信息失败")
	}
	if strategyEntity == nil {
		return gerror.New("策略不存在")
	}

	// 检查策略是否激活
	if !strategyEntity.IsActive {
		return gerror.New("策略未激活，无法启动")
	}

	// 检查策略是否已在运行
	if strategyEntity.Status == "running" {
		return gerror.New("策略已在运行中")
	}

	// 这里应该调用策略管理器来启动策略
	// manager := strategy.GetManager()
	// err = manager.StartStrategy(id)
	// if err != nil {
	// 	return gerror.Wrap(err, "启动策略失败")
	// }

	// 更新策略状态
	err = dao.Strategy.UpdateStatus(ctx, id, "running")
	if err != nil {
		return gerror.Wrap(err, "更新策略状态失败")
	}

	// 记录策略日志
	log := &entity.StrategyLog{
		StrategyId: id,
		Level:      "INFO",
		Message:    "策略启动",
		Context:    "",
		CreatedAt:  gtime.Now(),
	}
	_, err = dao.StrategyLog.Insert(ctx, log)
	if err != nil {
		g.Log().Warning(ctx, "记录策略日志失败", "error", err)
	}

	g.Log().Info(ctx, "启动策略成功", "id", id, "name", strategyEntity.Name)
	return nil
}

// Stop 停止策略
func (s *StrategyService) Stop(ctx context.Context, id int) error {
	// 检查策略是否存在
	strategyEntity, err := dao.Strategy.GetById(ctx, id)
	if err != nil {
		return gerror.Wrap(err, "获取策略信息失败")
	}
	if strategyEntity == nil {
		return gerror.New("策略不存在")
	}

	// 检查策略是否在运行
	if strategyEntity.Status != "running" {
		return gerror.New("策略未在运行中")
	}

	// 这里应该调用策略管理器来停止策略
	// manager := strategy.GetManager()
	// err = manager.StopStrategy(id)
	// if err != nil {
	// 	return gerror.Wrap(err, "停止策略失败")
	// }

	// 更新策略状态
	err = dao.Strategy.UpdateStatus(ctx, id, "stopped")
	if err != nil {
		return gerror.Wrap(err, "更新策略状态失败")
	}

	// 记录策略日志
	log := &entity.StrategyLog{
		StrategyId: id,
		Level:      "INFO",
		Message:    "策略停止",
		Context:    "",
		CreatedAt:  gtime.Now(),
	}
	_, err = dao.StrategyLog.Insert(ctx, log)
	if err != nil {
		g.Log().Warning(ctx, "记录策略日志失败", "error", err)
	}

	g.Log().Info(ctx, "停止策略成功", "id", id, "name", strategyEntity.Name)
	return nil
}

// GetTypeList 获取策略类型列表
func (s *StrategyService) GetTypeList(ctx context.Context) ([]string, error) {
	types, err := dao.Strategy.GetTypeList(ctx)
	if err != nil {
		return nil, gerror.Wrap(err, "获取策略类型列表失败")
	}
	return types, nil
}

// GetActiveStrategies 获取激活的策略列表
func (s *StrategyService) GetActiveStrategies(ctx context.Context) ([]*entity.Strategy, error) {
	strategies, err := dao.Strategy.GetActiveStrategies(ctx)
	if err != nil {
		return nil, gerror.Wrap(err, "获取激活策略列表失败")
	}
	return strategies, nil
}

// GetRunningStrategies 获取运行中的策略列表
func (s *StrategyService) GetRunningStrategies(ctx context.Context) ([]*entity.Strategy, error) {
	strategies, err := dao.Strategy.GetRunningStrategies(ctx)
	if err != nil {
		return nil, gerror.Wrap(err, "获取运行中策略列表失败")
	}
	return strategies, nil
}

// UpdatePerformance 更新策略性能
func (s *StrategyService) UpdatePerformance(ctx context.Context, strategyId int, performance *entity.StrategyPerformanceEntity) error {
	performance.StrategyId = strategyId
	err := dao.StrategyPerformance.Upsert(ctx, performance)
	if err != nil {
		return gerror.Wrap(err, "更新策略性能失败")
	}
	return nil
}

// CreateSignal 创建交易信号
func (s *StrategyService) CreateSignal(ctx context.Context, signal *entity.TradingSignal) error {
	_, err := dao.TradingSignal.Insert(ctx, signal)
	if err != nil {
		return gerror.Wrap(err, "创建交易信号失败")
	}
	return nil
}

// GetLogs 获取策略日志
func (s *StrategyService) GetLogs(ctx context.Context, strategyId, page, limit int) ([]*entity.StrategyLog, int, error) {
	// 设置默认值
	if page == 0 {
		page = 1
	}
	if limit == 0 {
		limit = 20
	}

	logs, err := dao.StrategyLog.GetListByStrategyId(ctx, strategyId, page, limit)
	if err != nil {
		return nil, 0, gerror.Wrap(err, "获取策略日志失败")
	}

	total, err := dao.StrategyLog.GetCountByStrategyId(ctx, strategyId)
	if err != nil {
		return nil, 0, gerror.Wrap(err, "获取策略日志总数失败")
	}

	return logs, total, nil
}